<template>
  <el-card class="container">
    <el-form ref="form" :model="spu" :rules="rules" label-width="80px">
      <el-form-item label="SPU名称" prop="spuName">
        <el-input v-model="spu.spuName" placeholder="请输入SPU名称" />
      </el-form-item>
      <el-form-item label="SPU品牌" prop="tmId">
        <el-select v-model="spu.tmId" placeholder="请选择SPU品牌">
          <el-option
            v-for="tm in trademarkList"
            :key="tm.id"
            :label="tm.tmName"
            :value="tm.id"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="SPU描述" prop="description">
        <el-input
          v-model="spu.description"
          type="textarea"
          :rows="2"
          placeholder="请输入SPU描述"
        />
      </el-form-item>
      <el-form-item label="SPU图片" prop="spuImgList">
        <el-upload
          ref="upload"
          :action="`${baseAPI}/admin/product/fileUpload`"
          list-type="picture-card"
          :on-preview="handlePictureCardPreview"
          :on-remove="handleRemove"
          :on-success="handleAvatarSuccess"
          :before-upload="beforeAvatarUpload"
          :limit="9"
          :on-exceed="handleExceed"
          :file-list="imgList"
        >
          <i class="el-icon-plus" />
          <div slot="tip" class="el-upload__tip">
            只能上传jpg/png文件，且不超过500kb
          </div>
        </el-upload>
        <el-dialog :visible.sync="dialogVisible" width="30%">
          <!-- eslint-disable-next-line -->
          <img width="100%" :src="dialogImageUrl" alt="" />
        </el-dialog>
      </el-form-item>

      <el-form-item label="销售属性" prop="spuSaleAttrList">
        <el-select
          v-model="baseSaleAttr"
          :placeholder="`还剩${baseSaleAttrList.length}个销售属性`"
        >
          <el-option
            v-for="saleAttr in baseSaleAttrList"
            :key="saleAttr.id"
            :label="saleAttr.name"
            :value="`${saleAttr.id}:${saleAttr.name}`"
          />
        </el-select>
        <el-button
          type="primary"
          icon="el-icon-plus"
          class="sale-attr-btn"
          :disabled="!baseSaleAttr"
          @click="addSaleAttr"
        >
          添加属性值
        </el-button>
        <el-table :data="spu.spuSaleAttrList" border class="container-table">
          <el-table-column
            type="index"
            label="序号"
            width="50"
            align="center"
          />
          <el-table-column
            label="属性名"
            width="100"
            align="center"
            prop="saleAttrName"
          />
          <el-table-column v-slot="{ row, $index }" label="属性值列表">
            <el-tag
              v-for="(saleValue, index) in row.spuSaleAttrValueList"
              :key="saleValue.saleAttrValueName"
              closable
              size="medium"
              class="spu-tag"
              @close="delSaleValue(row.spuSaleAttrValueList, index)"
            >
              {{ saleValue.saleAttrValueName }}
            </el-tag>
            <el-button
              v-show="!row.isEdit"
              size="mini"
              icon="el-icon-plus"
              @click="showEdit(row, $index)"
            >
              添加属性值
            </el-button>
            <el-input
              v-show="row.isEdit"
              :ref="$index"
              v-model="attrValue"
              class="spu-edit"
              size="mini"
              placeholder="请输入属性值名称"
              @blur="setAttrValue(row)"
              @keyup.native.enter="$event.target.blur"
            />
          </el-table-column>
          <el-table-column
            v-slot="{ row, $index }"
            label="操作"
            width="100"
            align="center"
          >
            <el-tooltip content="删除" placement="top">
              <el-button
                size="mini"
                type="danger"
                class="el-icon-delete"
                @click="delSaleAttr(row, $index)"
              />
            </el-tooltip>
          </el-table-column>
        </el-table>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submit">确定</el-button>
        <el-button @click="cancel">取消</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</template>

<script>
import { mapState, mapMutations } from 'vuex'
import { reqGetAllTrademarkList } from '@/api/product/trademark'
import {
  reqGetBaseSaleAttrList,
  reqSaveSpu,
  reqGetSpuInfo,
  reqGetSpuImageList
} from '@/api/product/spu'

export default {
  name: 'AddOrUpdateSpu',
  data() {
    const validator = (rule, value, callback) => {
      if (!this.spu.spuSaleAttrList.length) {
        callback('请添加至少一个销售属性')
        return
      }

      const hasSpuSaleAttrValueList = this.spu.spuSaleAttrList.every(
        (saleAttr) => !!saleAttr.spuSaleAttrValueList.length
      )

      if (!hasSpuSaleAttrValueList) {
        callback('每一个销售属性都要添加至少一个属性值')
        return
      }

      callback()
    }
    return {
      dialogImageUrl: '',
      dialogVisible: false,
      baseAPI: process.env.VUE_APP_BASE_API,
      spu: {
        spuName: '', // 名称
        tmId: '', // 品牌
        description: '', // 描述
        spuImgList: [], // 图片
        spuSaleAttrList: [] // 销售属性
      },
      rules: {
        spuName: [
          { required: true, message: '请输入SPU名称', trigger: 'blur' }
        ],
        tmId: [{ required: true, message: '请输入SPU品牌', trigger: 'change' }],
        description: [
          { required: true, message: '请输入SPU描述', trigger: 'blur' }
        ],
        spuImgList: [{ required: true, message: '请上传SPU图片' }],
        spuSaleAttrList: [
          { required: true, validator: validator, trigger: 'blur' }
        ]
      },
      trademarkList: [], // 品牌列表
      baseSaleAttrList: [], // 销售属性列表
      baseSaleAttr: '', // 选中的销售属性
      attrValue: '',
      imgList: []
    }
  },
  computed: {
    ...mapState('category', ['category3Id']),
    ...mapState('spu', ['spuId'])
  },
  async mounted() {
    // 添加SPU
    const [trademarkListRes, baseSaleAttrListRes] = await Promise.allSettled([
      reqGetAllTrademarkList(),
      reqGetBaseSaleAttrList()
    ])
    if (trademarkListRes.status === 'fulfilled') {
      this.trademarkList = trademarkListRes.value
    } else {
      this.$message({
        type: 'error',
        message: '获取品牌数据失败'
      })
    }
    if (baseSaleAttrListRes.status === 'fulfilled') {
      this.baseSaleAttrList = baseSaleAttrListRes.value
    } else {
      this.$message({
        type: 'error',
        message: '获取销售属性数据失败'
      })
    }
    if (this.spuId) {
      // 修改SPU
      const { spuId } = this
      const [spuRes, spuImageList] = await Promise.allSettled([
        reqGetSpuInfo(spuId),
        reqGetSpuImageList(spuId)
      ])
      if (spuRes.status === 'fulfilled') {
        this.spu = spuRes.value
        spuRes.value.spuSaleAttrList.forEach((sale) => {
          this.baseSaleAttrList = this.baseSaleAttrList.filter(
            (saleAttr) => saleAttr.id !== sale.baseSaleAttrId
          )
        })
      } else {
        this.$message({
          type: 'error',
          message: '获取spu数据失败'
        })
      }
      if (spuImageList.status === 'fulfilled') {
        this.imgList = spuImageList.value.map((img) => ({
          name: img.imgName,
          url: img.imgUrl
        }))
      } else {
        this.$message({
          type: 'error',
          message: '获取spu图片列表失败'
        })
      }
      this.$nextTick(() => {
        this.$refs.upload.submit()
      })
    }
  },
  methods: {
    ...mapMutations('spu', ['SET_SPU_ID']),
    // 删除图片触发
    handleRemove(file) {
      this.spu.spuImgList = this.spu.spuImgList.filter(
        (img) => img.imgUrl !== file.response.data
      )
    },
    // 预览图片触发
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url
      this.dialogVisible = true
    },
    // 上传成功触发
    handleAvatarSuccess(res, file) {
      this.spu.spuImgList.push({
        imgName: file.name,
        imgUrl: res.data
      })
      this.$refs.form.clearValidate(['spuImgList'])
    },
    // 上传之前触发
    beforeAvatarUpload(file) {
      const validFileType = ['image/jpeg', 'image/jpg', 'image/png']
      const isValidFileType = validFileType.indexOf(file.type) > -1
      const isLt = file.size / 1024 < 500

      if (!isValidFileType) {
        this.$message.error('上传头像图片只能是 JPG 或 PNG 格式!')
      }
      if (!isLt) {
        this.$message.error('上传头像图片大小不能超过 500KB!')
      }
      return isValidFileType && isLt
    },
    // 超出图片个数触发
    handleExceed() {
      this.$message({
        type: 'error',
        message: '图片数量超出，最多只能上传九张图片'
      })
    },
    // 添加销售属性
    addSaleAttr() {
      const [baseSaleAttrId, saleAttrName] = this.baseSaleAttr.split(':')
      this.spu.spuSaleAttrList.push({
        baseSaleAttrId,
        saleAttrName,
        spuSaleAttrValueList: []
      })

      this.baseSaleAttrList = this.baseSaleAttrList.filter(
        (saleAttr) => saleAttr.id !== +baseSaleAttrId
      )

      this.baseSaleAttr = ''
    },
    // 删除销售属性
    delSaleAttr(row, index) {
      this.spu.spuSaleAttrList.splice(index, 1)
      this.baseSaleAttrList.push({
        id: +row.baseSaleAttrId,
        name: row.saleAttrName
      })
      this.baseSaleAttrList.sort((a, b) => a.id - b.id)
    },
    // 显示编辑模式切换
    showEdit(row, $index) {
      this.$set(row, 'isEdit', true)
      this.$nextTick(() => {
        this.$refs[$index].focus()
      })
    },
    // 设置属性值，失去焦点或回车触发
    setAttrValue(row) {
      const { attrValue } = this
      if (attrValue.trim()) {
        row.spuSaleAttrValueList.push({
          saleAttrValueName: attrValue.trim(),
          baseSaleAttrId: +row.baseSaleAttrId,
          saleAttrName: row.saleAttrName
        })
        this.attrValue = ''
      }
      // 编辑-显示模式切换
      row.isEdit = false
    },
    delSaleValue(spuSaleAttrValueList, index) {
      spuSaleAttrValueList.splice(index, 1)
    },
    submit() {
      this.$refs.form.validate(async(valid) => {
        if (valid) {
          const { category3Id } = this
          const {
            description,
            spuImgList: spuImageList,
            spuName,
            spuSaleAttrList,
            tmId
          } = this.spu

          const data = {
            category3Id,
            description,
            spuImageList,
            spuName,
            spuSaleAttrList,
            tmId
          }

          await reqSaveSpu(data)

          this.$message({
            type: 'success',
            message: '添加SPU成功~'
          })

          this.cancel()
        }
      })
    },
    cancel() {
      this.$emit('updateIsShow', 1)
      this.SET_SPU_ID(0)
    }
  }
}
</script>

<style scoped>
.sale-attr-btn {
  margin-left: 10px;
}
.spu-edit {
  width: 150px;
}
.spu-tag {
  margin-right: 10px;
}
</style>
